﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Flyweight
{
    class Program
    {
        static void Main(string[] args)
        {
            FlyweightFactory f = new FlyweightFactory();
            Flyweight fa = f.GetFlyweight("A");
            Flyweight fa1 = f.GetFlyweight("A");
            Flyweight fb = f.GetFlyweight("B");
            Flyweight fb1 = f.GetFlyweight("B");
            Flyweight fc = f.GetFlyweight("C");
            Flyweight fc1 = f.GetFlyweight("C");

            Console.WriteLine(fa == fa1);
            Console.WriteLine(fb == fb1);
            Console.WriteLine(fc == fc1);
            fa.Display();
            fb.Display();
            fc.Display();

            Console.Read();
        }
    }

    class FlyweightFactory
    {
        private Hashtable flyweights = new Hashtable();

        public FlyweightFactory()
        { }

        public Flyweight GetFlyweight(string key)
        {
            Flyweight flyweight = null;
            if (flyweights.ContainsKey(key))
            {
                flyweight = flyweights[key] as Flyweight;
            }
            else
            {
                switch (key)
                {
                    case "A": flyweight = new ConcreteFlyweightA(); break;
                    case "B": flyweight = new ConcreteFlyweightB(); break;
                    default: flyweight = new ConcreteFlyweightC(); break;
                }
                flyweights.Add(key, flyweight);
            }

            return flyweight;
        }
    }

    abstract class Flyweight
    {
        public Flyweight()
        {
            Console.WriteLine("{0} is initing", this.GetType().Name);
        }
        public abstract void Display();
    }

    class ConcreteFlyweightA : Flyweight
    {
        public override void Display()
        {
            Console.WriteLine("Display method of {0} be called"
                , this.GetType().Name);
        }
    }

    class ConcreteFlyweightB : Flyweight
    {
        public override void Display()
        {
            Console.WriteLine("Display method of {0} be called"
                , this.GetType().Name);
        }
    }

    class ConcreteFlyweightC : Flyweight
    {
        public override void Display()
        {
            Console.WriteLine("Display method of {0} be called"
                , this.GetType().Name);
        }
    }
}
